namespace MoonFramework.Net;

public static class DataSerializer
{
    public static byte[] Serialize(params object?[] args)
    {
        using (MemoryStream stream = new())
        {
            foreach (var arg in args)
            {
                switch (arg)
                {
                    case null:
                        stream.WriteByte(0); //写入数据类型
                        break;
                    case sbyte sArg:
                        stream.WriteByte(1);
                        stream.WriteByte((byte)sArg);
                        break;
                    case byte bArg:
                        stream.WriteByte(2);
                        stream.WriteByte(bArg);
                        break;
                    case short shArg:
                        stream.WriteByte(3);
                        var arr = BitConverter.GetBytes(shArg);
                        if(BitConverter.IsLittleEndian) Array.Reverse(arr);
                        stream.Write(arr, 0, arr.Length);
                        break;
                    case ushort ushArg:
                        stream.WriteByte(4);
                        stream.Write(VariantEncode((long)ushArg));
                        break;
                    case int iArg:
                        stream.WriteByte(5);
                        stream.Write(VariantEncode((long)iArg));
                        break;
                    case uint uiArg:
                        stream.WriteByte(6);
                        stream.Write(VariantEncode((long)uiArg));
                        break;
                    case long lArg:
                        stream.WriteByte(7);
                        stream.Write(VariantEncode((long)lArg));
                        break;
                    case ulong ulArg:
                        stream.WriteByte(8);
                        stream.Write(VariantEncode((long)ulArg));
                        break;
                    case float fArg:
                        stream.WriteByte(9);
                        stream.Write(BitConverter.GetBytes((long)fArg));
                        break;
                    case double dArg:
                        stream.WriteByte(10);
                        stream.Write(BitConverter.GetBytes((long)dArg));
                        break;
                }
            }
            return null;
        }
    }
    
    // Variant 编码
    public static byte[] VariantEncode(long value)
    {
        if (value >= 562949953421312) //大于 7位效率不如 原始二进制方法
        {
            byte[] bytes = BitConverter.GetBytes(value);
            if (BitConverter.IsLittleEndian)
                Array.Reverse(bytes);
            return bytes;
        }
        var list = new List<byte>();
        while (value > 0)
        {
            byte b = (byte)(value & 0x7F);  // 获取低7位
            value >>= 7;  // 右移7位
            if (value > 0) 
            {
                b |= 0x80;  // 如果有更多数据，设置最高位为1
            }
            list.Add(b);
        }
        return list.ToArray();
    }

    // Variant 解码
    public static ulong VariantDecode(byte[] buffer)
    {
        if (buffer.Length >= 8)
        {
            if (BitConverter.IsLittleEndian)
                Array.Reverse(buffer);
            return BitConverter.ToUInt64(buffer);
        }
        ulong value = 0;
        int shift = 0;
        foreach (byte b in buffer)
        {
            value |= (ulong)(b & 0x7F) << shift;  // 将低7位放到正确位置
            if ((b & 0x80) == 0) // 如果最高位为0，表示解码结束
            {
                break;
            }
            shift += 7;
        }
        return value;
    }

    // 计算 Variant 编码所需的字节数
    public static int VariantSize(ulong value)
    {
        int size = 0;
        do
        {
            size++;
            value >>= 7;
        } while (value > 0);
        return size;
    }
}
